// 注意：本js库适用于vue-cli，对于原生html在事件绑定中由于运行机制的问题可能须有修改一下代码
// 方法库分类： 1.基础通用；2.信息处理类（一进一出，一进多出，多进多出）；3.功能交互类；

// 1.基础通用组件

// 异步方法
let asyncTime = function (callback, time) {
  let st = setTimeout(() => {
    callback()
    clearTimeout(st)
  }, time);
}

// 加密
var toCode = function (str) {  //加密字符串
  //定义密钥，36个字母和数字
  var key = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  var l = key.length;  //获取密钥的长度
  var a = key.split("");  //把密钥字符串转换为字符数组
  var s = "", b, b1, b2, b3;  //定义临时变量
  for (var i = 0; i < str.length; i++) {  //遍历字符串
    b = str.charCodeAt(i);  //逐个提取每个字符，并获取Unicode编码值
    b1 = b % l;  //求Unicode编码值得余数
    b = (b - b1) / l;  //求最大倍数
    b2 = b % l;  //求最大倍数的于是
    b = (b - b2) / l;  //求最大倍数
    b3 = b % l;  //求最大倍数的余数
    s += a[b3] + a[b2] + a[b1];  //根据余数值映射到密钥中对应下标位置的字符
  }
  return s;  //返回这些映射的字符
}

// 解密
var fromCode = function (str) {
  try {
    let test = JSON.parse(str)
    if (Object.prototype.toString.call(test) === '[object Object]') {
      return str
    }
  } catch (error) {
    sessionStorage.setItem('fromCodeError', error)
  }
  //定义密钥，36个字母和数字
  var key = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  var l = key.length;  //获取密钥的长度
  var b, b1, b2, b3, d = 0, s;  //定义临时变量
  s = new Array(Math.floor(str.length / 3));  //计算加密字符串包含的字符数，并定义数组
  b = s.length;  //获取数组的长度
  for (var i = 0; i < b; i++) {  //以数组的长度循环次数，遍历加密字符串
    b1 = key.indexOf(str.charAt(d));  //截取周期内第一个字符串，计算在密钥中的下标值
    d++;
    b2 = key.indexOf(str.charAt(d));  //截取周期内第二个字符串，计算在密钥中的下标值
    d++;
    b3 = key.indexOf(str.charAt(d));  //截取周期内第三个字符串，计算在密钥中的下标值
    d++;
    s[i] = b1 * l * l + b2 * l + b3  //利用下标值，反推被加密字符的Unicode编码值
  }
  b = eval("String.fromCharCode(" + s.join(',') + ")"); //用fromCharCode()算出字符串
  return b;  //返回被解密的字符串
}

// 防抖：防止重复点击触发事件(又分为重复点击停止后触发和重复点击的第一次点击触发，一般用前者)
function debounce(fn, time) {
  let _arguments = arguments
  let timeout = null
  return () => {
    if (timeout) {
      clearTimeout(timeout)
    }
    timeout = setTimeout(() => {
      fn.call(this, _arguments)
    }, time);
  }
}
// vue防抖函数改造 fnName: String
function VueDebounce(fnName, time) {
  let timeout = null;
  return function () {
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      this[fnName]();
    }, time);
  };
}
// 节流：指定时间间隔内只会执行一次任务
function throttle(fn, time) {
  let _arguments = arguments
  let canRun = true
  return () => {
    if (!canRun) return
    canRun = false
    setTimeout(() => {
      fn.call(this, _arguments)
      canRun = true
    }, time);
  }
}
// vue节流函数改造 fnName: String
function VueThrottle(fnName, time) {
  let canRun = true
  return () => {
    if (!canRun) return
    canRun = false
    setTimeout(() => {
      this[fnName]();
      canRun = true
    }, time);
  }
}

// 类型判断
/*
  typeof可以识别出基本类型boolean,number,undefined,string,symbol，但是不能识别null。不能识别引用数据类型，会把null、array、object统一归为object类型,但是可以识别出function。

instanceof不能识别出基本的数据类型 number、boolean、string、undefined、unll、symbol。
但是可以检测出引用类型，如array、object、function，同时对于是使用new声明的类型，它还可以检测出多层继承关系。

  所以typeof可以用来识别一些基本类型，引用类型可以使用instanceof。
*/
function typeString(params) {
  return Object.prototype.toString.call(params)
}

function isBoolean(params) {
  return typeString(params) == '[object Boolean]' || typeof params == 'boolean'
}
function isNumber(params) {
  return typeString(params) == '[object Number]' || typeof params == 'number'
}
function isString(params) {
  return typeString(params) == '[object String]' || typeof params == 'string'
}
function isUndefined(params) {
  return typeString(params) == '[object Undefined]' || typeof params == 'undefined'
}
function isNull(params) {
  return typeString(params) == '[object Null]'
}
function isArray(params) {
  return typeString(params) == '[object Array]' || params instanceof Array
}
function isObject(params) {
  return typeString(params) == '[object Object]' || params instanceof Object
}
function isFunction(params) {
  return typeString(params) == '[object Function]' || typeof params == 'function' || params instanceof Function;
}
function isSymbol(params) {
  return typeString(params) == '[object Symbol]' || typeof params == 'symbol'
}


// 2.信息处理

// 人民币大写
let smallToBig = function (money) {
  //  将数字金额转换为大写金额
  var cnNums = new Array(
    "零",
    "壹",
    "贰",
    "叁",
    "肆",
    "伍",
    "陆",
    "柒",
    "捌",
    "玖"
  ); //汉字的数字
  var cnIntRadice = new Array("", "拾", "佰", "仟"); //基本单位
  var cnIntUnits = new Array("", "万", "亿", "兆"); //对应整数部分扩展单位
  var cnDecUnits = new Array("角", "分", "毫", "厘"); //对应小数部分单位
  var cnInteger = "整"; //整数金额时后面跟的字符
  var cnIntLast = "元"; //整数完以后的单位
  //最大处理的数字
  var maxNum = 999999999999999.99;
  var integerNum; //金额整数部分
  var decimalNum; //金额小数部分
  //输出的中文金额字符串
  var chineseStr = "";
  // let parts; //分离金额后用的数组，预定义
  if (money == "") {
    return "";
  }

  money = parseFloat(money);
  if (isNaN(money)) {
    return "输入有误";
  }
  if (money >= maxNum) {
    //超出最大处理数字
    return "超出最大处理数字";
  }
  if (money == 0) {
    chineseStr = cnNums[0] + cnIntLast + cnInteger;
    return chineseStr;
  }

  //四舍五入保留两位小数,转换为字符串
  money = Math.round(money * 100).toString();
  integerNum = money.substr(0, money.length - 2);
  decimalNum = money.substr(money.length - 2);

  //获取整型部分转换
  if (parseInt(integerNum, 10) > 0) {
    var zeroCount = 0;
    var IntLen = integerNum.length;
    for (let i = 0; i < IntLen; i++) {
      let n = integerNum.substr(i, 1);
      var p = IntLen - i - 1;
      var q = p / 4;
      var m = p % 4;
      if (n == "0") {
        zeroCount++;
      } else {
        if (zeroCount > 0) {
          chineseStr += cnNums[0];
        }
        //归零
        zeroCount = 0;
        chineseStr += cnNums[parseInt(n)] + cnIntRadice[m];
      }
      if (m == 0 && zeroCount < 4) {
        chineseStr += cnIntUnits[q];
      }
    }
    chineseStr += cnIntLast;
  }
  //小数部分
  if (decimalNum != "") {
    var decLen = decimalNum.length;
    for (let i = 0; i < decLen; i++) {
      let n = decimalNum.substr(i, 1);
      if (n != "0") {
        chineseStr += cnNums[Number(n)] + cnDecUnits[i];
      }
    }
  }
  if (chineseStr == "") {
    chineseStr += cnNums[0] + cnIntLast + cnInteger;
  } else if (decimalNum == "" || /^0*$/.test(decimalNum)) {
    chineseStr += cnInteger;
  }
  return chineseStr;
}

// 金额格式 100,000,000
function moneyFormat(money) {
  if (money && money != null) {
    money = String(money);
    var left = money.split(".")[0],
      right = money.split(".")[1];
    right = right
      ? right.length >= 2
        ? "." + right.substr(0, 2)
        : "." + right + "0"
      : "";
    var temp = left
      .split("")
      .reverse()
      .join("")
      .match(/(\d{1,3})/g);
    return (
      (Number(money) < 0 ? "-" : "") +
      temp.join(",").split("").reverse().join("") +
      right
    );
  } else if (money === 0) {
    // 注意===在这里的使用，如果传入的money为0,if中会将其判定为boolean类型，故而要另外做===判断
    return "0";
  } else {
    return "";
  }
}

// 获取url参数
function getQueryVariable(variable) {
  var query = window.location.search.substring(1);
  var vars = query.split("&");
  for (var i = 0; i < vars.length; i++) {
    var pair = vars[i].split("=");
    if (pair[0] == variable) { return pair[1]; }
  }
  return (false);
}

// 3.功能交互类组件
let callphone = (phone) => {
  if (phone == '') {
    return false
  }
  window.location.href = `tel:${phone}`
}


export {
  callphone,
  smallToBig,
  asyncTime,
  debounce,
  throttle,
  VueDebounce,
  VueThrottle,
  moneyFormat,
  toCode,
  fromCode,
  getQueryVariable,
  isBoolean,
  isNumber,
  isString,
  isUndefined,
  isNull,
  isArray,
  isObject,
  isFunction,
  isSymbol,
}